// @description: 代理操作
// @auth: bigkai
// @time: 2020/7/26

package crawl

import (
	"fmt"
	"github.com/PuerkitoBio/goquery"
	"golang.org/x/text/encoding/simplifiedchinese"
	"math/rand"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

const BASE_PROXY_URL string = "http://www.66ip.cn/"
var proxyChannel = make(chan ProxyIp, 50)

// 初始化代理池
func InitProxyPoll(size int) {

	if size <= 0 {
		return
	}

	for i := 1; ; i++ {

		resp, err := http.Get(BASE_PROXY_URL + strconv.Itoa(i) + ".html")
		if err != nil {
			panic(err)
		}
		document, err := goquery.NewDocumentFromReader(resp.Body)
		document.Find("div.containerbox").Find("table tbody tr").Each(func(i int, selection *goquery.Selection) {
			if i != 0 {
				proxyIp := ProxyIp{}

				selection.Find("td").Each(func(i int, selection *goquery.Selection) {
					text := selection.Text()
					text = EncoderToUtf8(text)
					switch i {
					case 0:
						proxyIp.Ip = text
					case 1:
						proxyIp.Port, _ = strconv.Atoi(text)
					case 2:
						proxyIp.Place = text
					case 3:
						proxyIp.Anonymous = text
					case 4:
						proxyIp.CheckTime = text
					}
				})

				proxyChannel <- proxyIp
				if len(proxyChannel) == size {
					return
				}
			}
		})
	}
}

// 获取代理池
func GetProxyPool() chan ProxyIp{
	return proxyChannel
}

// 编码转换，处理乱码
func EncoderToUtf8(text string) string {
	dst := make([]byte, len(text) * 2)
	encoder := simplifiedchinese.GBK.NewDecoder()
	nDst, _, err := encoder.Transform(dst, []byte(text), true)
	if err != nil {
		panic(err)
	}
	return string(dst[:nDst])
}


// 返回代理游览器
func getAgent() string {
	agent  := [...]string{
		"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0",
		"Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11",
		"Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11",
		"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)",
		"Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
		"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; The World)",
		"User-Agent,Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
		"User-Agent, Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)",
		"User-Agent,Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
	}

	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	len := len(agent)
	return agent[r.Intn(len)]
}

// 使用代理获取数据
func requestByProxy(tturl string, proxyIpObject ProxyIp) *http.Response {
	request, _ := http.NewRequest("GET", tturl, nil)
	//随机返回User-Agent 信息
	request.Header.Set("User-Agent", getAgent())
	request.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
	request.Header.Set("Connection", "keep-alive")
	proxy, err := url.Parse("http://" + proxyIpObject.Ip + ":" + strconv.Itoa(proxyIpObject.Port))
	if err != nil {
		panic(err)
	}

	//设置超时时间
	timeout := time.Duration(10 * time.Second)

	fmt.Printf("使用代理:%s\n",proxy)
	client := &http.Client{}
	client = &http.Client{
		Transport: &http.Transport{
			Proxy: http.ProxyURL(proxy),
		},
		Timeout: timeout,
	}

	response, err := client.Do(request)
	if err != nil {
		errStr := err.Error()
		switch {
		case strings.Contains(errStr, "timeout"):
			fmt.Println("Timeout")
			return nil
		case strings.Contains(errStr, "no such host"):
			fmt.Println("Unknown host")
		case strings.Contains(errStr, "connection refused"):
			fmt.Println("Connection refused")
		default:
			fmt.Printf("Unknown error:%s\n", errStr)
		}
	}

	return response
}